/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.ipti.br.tag.bean;

import org.ipti.br.tag.bean.dataManipulation.UnityScheduleEvent;
import org.ipti.br.tag.bean.dataManipulation.UnityScheduleModel;
import org.ipti.br.tag.bo.ActorBO;
import org.ipti.br.tag.bo.ActorScheduleBO;
import org.ipti.br.tag.bo.DisciplineBO;
import org.ipti.br.tag.bo.HumanBO;
import org.ipti.br.tag.bo.OrganizationBO;
import org.ipti.br.tag.bo.PersonageBO;
import org.ipti.br.tag.bo.TaskBO;
import org.ipti.br.tag.bo.UnityBO;
import org.ipti.br.tag.bo.UnityScheduleBO;
import org.ipti.br.tag.configuration.qualifiers.Responsible;
import org.ipti.br.tag.entity.Actor;
import org.ipti.br.tag.entity.Discipline;
import org.ipti.br.tag.entity.Human;
import org.ipti.br.tag.entity.Organization;
import org.ipti.br.tag.entity.Personage;
import org.ipti.br.tag.entity.Task;
import org.ipti.br.tag.entity.Unity;
import org.ipti.br.tag.entity.UnitySchedule;
import org.ipti.br.tag.entity.enums.WeekDay;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.inject.Inject;
import org.primefaces.event.SelectEvent;
import org.primefaces.model.ScheduleModel;
import org.ipti.br.tag.util.LoggerUtil;

/**
 *
 * @author israel
 */
@ManagedBean
@ViewScoped
public class UnityScheduleMB extends AppBaseBean implements Serializable {
    private static final int YEAR = Calendar.YEAR;
    private final int INITIAL_YEAR = 1986;
    private final int MAX_YEAR = 2013;
    
    @Inject private UnityBO unityBO;
    @Inject private UnityScheduleBO unityScheduleBO;
    @Inject private ActorScheduleBO actorScheduleBO;
    @Inject private TaskBO taskBO;
    @Inject private DisciplineBO disciplineBO;
    @Inject private PersonageBO personageBO;
    @Inject private ActorBO actorBO;
    @Inject private HumanBO humanBO;
    @Inject private OrganizationBO organizationBO;
    @Inject private SessionBean sessionBean;
    
    @Inject @Responsible
    private Unity resUnity;
    
    @Inject @Responsible
    private Personage responsible;
    
    private Unity unity;
    private Actor actor;
    private Personage allocated;
    private Organization organization;
    
    private List<Unity> unityList;
    private List<Actor> proposalActors;
    private List<Personage> personages;
    
    private ScheduleModel unityScheduleModel;
    private UnityScheduleEvent event = new UnityScheduleEvent();
    
    private int firstHour = 7;
    private boolean scheduleVisible;
    private Integer year = this.getActualYear();

    public UnityScheduleMB() {
        System.out.println("Criou");
    }

    @PostConstruct
    public void init() {
        System.out.println("Iniciando + "+getParameter("organizationID"));
        organization = (Organization) organizationBO.find(Long.parseLong(getParameter("organizationID")));
        loadUnityList();
    }

    public void loadSchedule() {
        System.out.println("loadSchedule");
        unityScheduleModel = new UnityScheduleModel();

        try{
            firstHour = unityScheduleBO.getInicialHour(unity);
            personages = personageBO.getAllocatedPersonages(unity.getOrganization());

            for (UnitySchedule us : unityScheduleBO.listForWeekDays(unity, null)) {
                event = new UnityScheduleEvent(us);
                event.updateWeekDay();
                unityScheduleModel.addEvent(event);
            }
            
            scheduleVisible = true;
        } catch(Exception e){
            scheduleVisible = false;
            addInfoMessage(null, "Erro ao gerar agenda", "Tente novamente ou contate o administrador");
            LoggerUtil.log("UnityScheduleBean:loadSchedule", Level.WARNING, "Erro ao gerar agenda", e);
        }
    }

    public void onDateSelect(SelectEvent selectEvent) {
        System.out.println("Date selected");
        event = new UnityScheduleEvent((Date) selectEvent.getObject());
        proposalActors = new ArrayList<Actor>();
        actor = new Actor();
        System.out.println("finishing selecting");
    }

    public void onEventSelect(SelectEvent selectEvent) {
        System.out.println("Event selected");
        try {
            event = (UnityScheduleEvent) selectEvent.getObject();
            System.out.println("US: "+((UnitySchedule) event.getData()).getId());
            proposalActors = actorBO.getActorDAO().listAllocateds((UnitySchedule) event.getData());
            
            actor = new Actor();
            actor.getActivated().setTime(unity.getActivated().getTime());
            if (unity.getDeactivated() != null) {
                actor.getDeactivated().setTime(unity.getDeactivated().getTime());
            }
        } catch (Exception ex) {
            String msg = "Erro ao selecionar evento";
            addErrorMessage("scheduleForm", msg, "tente recarregar a página caso o erro persista");
            LoggerUtil.log("UnityScheduleBean:onEventSelect", Level.SEVERE, msg, ex);
        }
        System.out.println("finishing selected");
    }
    
    public void addActor(){
        Actor act;
        act = actor;
        proposalActors.add(act);
        for (Actor a : proposalActors) {
                  System.out.println(a.getPerson().getId());
            } 
        actor.getActivated().setTime(unity.getActivated().getTime());
        if(unity.getDeactivated() != null) {
            actor.getDeactivated().setTime(unity.getDeactivated().getTime());
        }
    }

    public void saveEvent() {
        System.out.println("saving event");
        try {
            UnitySchedule unitySchedule = (UnitySchedule) event.getData();
            unitySchedule.setUnity(unity);

            event.updateWeekDay();

            if (unitySchedule.getId() == null) {
                unityScheduleBO.create(unitySchedule);
                event.setId(String.valueOf(unitySchedule.getId()));
                unityScheduleModel.addEvent(event);
            } else {
                unityScheduleBO.edit(unitySchedule);
                unityScheduleModel.updateEvent(event);
            }
            
            this.saveActors(unitySchedule);
            
            addInfoMessage("scheduleForm", "Operação realizada com sucesso", null);
        } catch (Exception ex) {
            String msg = "Um erro inesperado foi encontrado";
            addErrorMessage("scheduleForm", msg, "Contate o administrador do sistema");
            LoggerUtil.log("UnityScheduleBean:addEvent", Level.SEVERE, msg, ex);
        }
        System.out.println("event saved");
    }

    public void saveActors(UnitySchedule schedule) {
        try {
            for (Actor a : proposalActors) {
                if (a.getPerson() != null) {
                    a.setPersonage(allocated);
                    a.setUnity(unity);
                    try{
                        actorBO.create(a);
                    }catch(Exception e){}
                    actorScheduleBO.createOrUpdate(a, schedule);
                }
            }
        } catch (Exception ex) {
            String msg = "Não foi possível criar ator, tente novamente";
            addErrorMessage("scheduleForm", msg, null);
            LoggerUtil.log("UnityScheduleBean:createActor", Level.SEVERE, msg, ex);
        }
    }

    public void remove() {
        try {
            UnitySchedule us = (UnitySchedule) event.getData();
            actorScheduleBO.remove(us);
            
            unityScheduleBO.remove(us);
            unityScheduleModel.deleteEvent(event);
            addInfoMessage("scheduleForm", "Operação realizada com sucesso", null);
        } catch (Exception ex) {
            String msg = "Operação não pôde ser realizada";
            addErrorMessage("scheduleForm", msg, "Contate o administrador do sistema para melhores informações");
            LoggerUtil.log("UnityScheduleBean:remove", Level.SEVERE, msg, ex);
        }
    }
    
    public void removeActor(Actor actor, UnitySchedule schedule) throws Exception{
        if(actor.getId() == null){
            proposalActors.remove(actor);
            return;
        }
        actorScheduleBO.remove(actor,schedule);
        actorBO.remove(actor);
    }

    public void loadUnityList() {
        scheduleVisible = false;
        if (year != null) {
            unityList = unityBO.unityChildren(
                    sessionBean.getLoggedActor().getUnity(),
                    organization, year);
        }
    }
    
    public List<Human> searchHuman(String query) {
        return humanBO.searchAllocatedHuman(query, responsible, resUnity, 10);
    }

    public WeekDay[] getDaysOfWeek() {
        return WeekDay.values();
    }

    public List<Task> getTaskList() {
        return taskBO.findAll();
    }

    public List<Discipline> getDisciplineList() {
        return disciplineBO.findAllOrder();
    }

    public ScheduleModel getUnityScheduleModel() {
        return unityScheduleModel;
    }

    public Integer getYear() {
        return year;
    }

    public void setYear(Integer year) {
        this.year = year;
    }

    public boolean isScheduleVisible() {
        return scheduleVisible;
    }

    public UnityScheduleEvent getEvent() {
        return event;
    }

    public void setEvent(UnityScheduleEvent event) {
        this.event = event;
    }

    public int getFirstHour() {
        return firstHour;
    }

    public Unity getUnity() {
        return unity;
    }

    public void setUnity(Unity unity) {
        this.unity = unity;
    }

    public Actor getActor() {
        return actor;
    }

    public void setActor(Actor actor) {
        this.actor = actor;
    }

    public Organization getOrganization() {
        return organization;
    }

    public void setOrganization(Organization organization) {
        this.organization = organization;
    }

    public Personage getAllocated() {
        return allocated;
    }

    public void setAllocated(Personage allocated) {
        this.allocated = allocated;
    }

    public List<Unity> getUnityList() {
        return unityList;
    }

    public List<Actor> getProposalActors() {
        return proposalActors;
    }

    public List<Personage> getPersonages() {
        return personages;
    }
}
